package hichecker.tools;

import java.awt.Color;
import java.awt.Component;

/**
 * Klasse, welche die Validierung von Eingaben regelt
 */
public class Validation {
	/**
	 * Prüft ob eine Eingabe ein Note darstellt
	 */
	public static boolean isGrade(String input) {
		if (input == null)
			return false;
		
		// erste und zweite Stelle
		int first;
		int second;
		
		switch (input.length()) {
			// Länge 1 => nur die Zahlen 1 bis 5
			case 1:
				try {
					first = Integer.parseInt(input);
				} catch (NumberFormatException e) {
					return false;
				}
				if (first > 5) return false; 
				break;
			// Länge 3 => an zweiter Stelle nur .0, .3, und .7 akzeptiert
			case 3:
				if (input.charAt(1) != ',' && input.charAt(1) != '.')
					return false;
				try {
					first = Integer.parseInt(input.substring(0,1));
					second = Integer.parseInt(input.substring(2,3));					
				} catch (NumberFormatException e) {
					e.printStackTrace();
					return false;
				}
				if (first > 5 || (second != 0 && second != 3 && second != 7) || (first >= 4 && second != 0))
					return false;
				break;
			// alles andere wird nicht akzeptiert
			default: return false;
		}
		return true;
	}
	
	/**
	 * Prüft ob eine Eingabe einer {@link Integer Integerzahl} mit angegebener Länge entspricht
	 * 
	 * @param input
	 */
	public static boolean isNumber(String input, long min, long max) {
		if (input == null)
			return false;
		input = input.trim();
		try {
			long in = Long.parseLong(input);
			return in >= min && in <= max;
		} catch (NumberFormatException e) {
			return false;
		}
	}
	
	/**
	 * Prüft
	 * @param input
	 * @param min
	 * @param max
	 * @return
	 */
	public static boolean isFloatingPoint(String input, float min, float max) {
		if (input == null)
			return false;
		input = input.trim();
		try {
			float in = Float.parseFloat(input);
			return in >= min && in <= max;
		} catch (NumberFormatException e) {
			return false;
		}
	}
	
	/**
	 * Prüft, ob die Eingabe eine ganzzahliger Prozentwert zwischen 0 und 100 ist
	 */
	public static boolean isPercent(String input) {
		return isNumber(input, 0, 100);
	}
	
	
	/**
	 * Prüft ob eine Eingabe ein Text bestehend aus Buchstaben (inkulsive Umlauten) und Leerzeichen
	 * mit einer bestimmten Länge ist
	 * 
	 * @param input
	 *            Falls die Länge keine Rolle spielt, muss <b>-1</b> angegeben werden
	 * @return leerer input wird als <b>{@code false}</b> zurückgegeben
	 */
	public static boolean isText(String input, int length) {
		if (input == null || input.length() == 0 || (length != -1 && input.length() > length))
			return false;
		return input.matches("[a-zA-ZüÜäÄöÖß' ]*");
	}
	
	/**
	 * Prüft, ob es sich um einen Titel, also z.Bsp. Prof. Dr. rer. nat. habil.
	 */
	public static boolean isTitle(String input, int length) {
		if (input == null)
			return false;
		input = input.replace("-", " ");
		if (length == -1) length = Integer.MAX_VALUE;
		return  input.length() == 0 || isText(input.replace(".", " "), length);
	}
	
	/**
	 * Prüft, ob es sich um eine valide RZ-ID handelt
	 * @param input
	 * @return
	 */
	public static boolean isRZID(String input) {
		if (input == null || input.length() != 5)
			return false;
		
		String letters = input.substring(0, 2);
		String number = input.substring(2, 5);
		
		if (!letters.matches("[a-zA-Z]*"))
			return false;
		
		try {
			int parse = Integer.parseInt(number);
			if (parse <= 0)
				return false;
			return true;
		} catch (NumberFormatException e) {
			return false;
		}
	}
	
	
	/**
	 * Prüft, ob es sich um eine valide E-Mail Adresse handelt
	 * @param input
	 * @return
	 */
	public static boolean isMail(String input) {
		if (input.length() > 50 || input.indexOf("@") != input.lastIndexOf("@"))
			return false;
		
		boolean result = true;
		// Mail an @ splitten
		String localPart = input.substring(0, input.indexOf("@"));
		String domainPart = input.substring(input.indexOf("@") + 1);;
		
		// Metazeichen für die Regular Expression ändern
		localPart = localPart.replace(".", "_");
		localPart = localPart.replace("?", "_");
		localPart = localPart.replace("^", "_");
		localPart = localPart.replace("$", "_");
		localPart = localPart.replace("*", "_");
		localPart = localPart.replace("+", "_");
		localPart = localPart.replace("|", "_");
		localPart = localPart.replace("{", "_");
		localPart = localPart.replace("}", "_");
		
		// Prüfen, ob localPart stimmt
		result &= localPart.matches("[A-Za-z0-9!#%&'-/=_`~]*");
		
		// Auf Unterstriche prüfen, um Punkte in Unterstriche ändern zu können
		if (domainPart.indexOf("_") != -1)
			return false;
		
		// Alle Punkte ändern, um sie vergleichen zu können
		domainPart = domainPart.replace(".", "_");
		
		// Es gibt garkein Punkt, also auch nichts der Form @example.org
		if (domainPart.indexOf("_") == -1)
			return false;
		
		// Erstmal gucken, ob die Eingabe an sich valide ist.
		result &= domainPart.matches("[A-Za-z0-9-_]*");
		
		for (int i = 0; i < domainPart.length(); i++) {
			// darf nicht mit - oder _ (also Punkt) beginnen bzw. enden
			if (i == 0 || i == domainPart.length() - 1)
				result &= !domainPart.substring(i, i+1).matches("[_,-]");
			else {
				// zwei aufeinanderfolgende Zeichen dürfen nicht _ oder - sein
				char now = domainPart.charAt(i);
				char next = domainPart.charAt(i+1);
				result &= 
					!((now == '_' && (next == '_' || next == '-')) || 
					(now == '-' && (next == '_' || next == '-')));			
			}
		}
		
		return result;
	}
	
	/**
	 * Färbt den Hintergrund einer Komponente ein, je nach Validität des Inhalts
	 */
	public static void setValidationColor(Component comp, boolean valid) {
		if (!valid) {
			comp.setBackground(new Color(255, 0, 0));
			comp.setForeground(new Color(255, 255, 255));
		} else {
			comp.setBackground(new Color(255, 255, 255));
			comp.setForeground(new Color(0, 0, 0));
		}
	}
}
